package weeny.util.io;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * A Iterator utility to go through every line of the input
 * 
 * @author weeny
 *
 */
public class LineIterator implements Iterator<String>, Iterable<String>{
	private BufferedReader reader = null;
	private String line = null;
	private boolean hasNext = false;
	private int currentLine = -1;
	private boolean closeAfterwards = true;
	private void updateLine(){
		try {
			line = reader.readLine();
			if (line == null && closeAfterwards) {
				reader.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		hasNext = line != null;
		currentLine += 1;
	}
	public LineIterator(InputStream is, boolean closeAfterwards) {
		this(is);
		this.closeAfterwards = closeAfterwards;
	}
	public LineIterator(String fileName, boolean closeAfterwards) {
		this(fileName);
		this.closeAfterwards = closeAfterwards;
	}
	public LineIterator(InputStream is){
		InputStreamReader isr = new InputStreamReader(is);
		this.reader = new BufferedReader(isr);
		updateLine();
	}
	public LineIterator(String fileName){
		try {
			FileReader fr = new FileReader(fileName);
			this.reader = new BufferedReader(fr);
			updateLine();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}
	public LineIterator(BufferedReader br) {
		this.reader = br;
		updateLine();
	}
	public boolean hasNext() {
		return hasNext;
	}
	public String next() {
		if (hasNext) {
			String result = line;
			updateLine();
			return result;
		}
		else{
			throw new NoSuchElementException("no more lines");
		}
	}
	public void remove() {
		throw new UnsupportedOperationException("This is just a reader!");
	}
	/**
	 * get the line id (from #0) of the line got from last called next().
	 * For example, if you have iter = new LineIterator(...), after you call
	 * iter.next() for the fist time; you can call lineNumber() to get 0;
	 */
	public int lineNumber(){
		return currentLine-1;
	}
	public Iterator<String> iterator() {
		return this;
	}
}